// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; using System.Text; using JetBrains.Annotations; namespace LargoCommon.Music { /// /// Harmonic Motive. /// [Serializable] public sealed class MelodicMotive { #region Fields /// /// Unique identifier. /// private string uniqueIdentifier; /// /// Melodic Structures. /// [NonSerialized] private IEnumerable melodicStructures; #endregion #region Constructors /// /// Initializes a new instance of the MelodicMotive class. /// /// Name of the motive. /// Melodic Structures. public MelodicMotive(string name, IEnumerable melodicStructures) //// MelodicCore core, : this() { if (melodicStructures == null) { return; } this.Name = name; //// BandType = (byte)mp.BandType; //// LineIndex = mp.Number; //// existsMelLine = (PartType == (byte)MelodicFunction.MelodicMotion); var barNumber = 1; foreach (var mstruct in melodicStructures) { if (mstruct == null) { continue; } mstruct.BarNumber = barNumber++; this.AddStructure(mstruct); } } /// /// Initializes a new instance of the class. /// public MelodicMotive() { this.melodicStructures = new List(); } #endregion #region Properties /// /// Gets or sets the name. /// /// /// The full name. /// [UsedImplicitly] public string Name { get; set; } //// CA1044 (FxCop) /// /// Gets or sets the number. /// /// /// Property description. /// public int Number { get; set; } /// /// Gets or sets the octave. /// /// /// The octave. /// [UsedImplicitly] public MusicalOctave Octave { get; set; } //// CA1044 (FxCop) /// /// Gets or sets the type of the part. /// /// /// The type of the part. /// [UsedImplicitly] public MelodicFunction MelodicFunction { get; set; } //// CA1044 (FxCop) /// /// Gets or sets the first bar number. /// /// /// The first bar number. /// public int FirstBarNumber { get; set; } /// /// Gets or sets the occurrence. /// /// /// The occurrence. /// public int Occurrence { get; set; } /// /// Gets or sets the melodic structures. /// /// /// The melodic structures. /// public IEnumerable MelodicStructures { get { Contract.Ensures(Contract.Result>() != null); if (this.melodicStructures == null) { throw new InvalidOperationException("Melodic structures are null."); } return this.melodicStructures; } set => this.melodicStructures = value ?? throw new ArgumentException(Localization.LocalizedMusic.String("Argument cannot be empty."), nameof(value)); } /// /// Gets the length. /// /// Property description. public int Length => ((List)this.MelodicStructures).Count; /// /// Gets a value indicating whether this instance is empty. /// /// /// The is empty. /// [UsedImplicitly] public bool IsEmpty => this.MelodicStructures.FirstOrDefault() == null; /// Gets list of all already defined tones. /// Property description. public string UniqueIdentifier { get { if (this.uniqueIdentifier != null) { return this.uniqueIdentifier; } var ident = new StringBuilder(); var melodicMotiveStructureList = this.MelodicStructures.ToList(); ident.Append(string.Format(CultureInfo.CurrentCulture, "#{0}#", melodicMotiveStructureList.Count)); //// ElementSchema, DecimalNumber, ms.StructuralCode foreach (var b in from mms in melodicMotiveStructureList where mms?.GetStructuralCode != null from b in mms.GetStructuralCode select b) { ident.Append(b); } this.uniqueIdentifier = ident.ToString(); return this.uniqueIdentifier; } } /// /// Gets or sets the name. /// /// /// Property description. /// [UsedImplicitly] public string Shortcut { get; set; } //// CA1044 (FxCop) #endregion #region Static Factory methods /// /// Simple melodic motive. /// /// The melodic struct. /// Returns value. [UsedImplicitly] public static MelodicMotive SimpleMelodicMotive(MelodicStructure melodicStruct) { if (melodicStruct == null) { return null; } var rm = new MelodicMotive(); melodicStruct.BarNumber = 1; rm.AddStructure(melodicStruct); return rm; } #endregion #region Public methods /// /// Melodic structure in bar. /// /// The bar number. /// Returns value. public MelodicStructure MelodicStructureInBar(int barNumber) { if (barNumber < 1) { throw new ArgumentOutOfRangeException(nameof(barNumber), "value must be positive"); } var cnt = this.MelodicStructures.Count(); if (cnt == 0) { return null; //// throw new ArgumentException("No melodic motive structure!"); } var idx = (barNumber - 1) % cnt; var structure = this.MelodicStructures.ElementAt(idx); return structure; } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// [UsedImplicitly] public override string ToString() { return this.Name; } /// /// Adds the structure. /// /// The structure. public void AddStructure(MelodicStructure structure) { ((List)this.MelodicStructures).Add(structure); } #endregion } }